package miniceduapp.views

import javafx.geometry.Pos
import javafx.scene.layout.Priority
import javafx.scene.paint.Color
import miniceduapp.bytecodde.Instruction
import miniceduapp.bytecodde.Label
import miniceduapp.helpers.hideHeader
import miniceduapp.viewmodels.BytecodeLine
import miniceduapp.viewmodels.BytecodeViewModel
import miniceduapp.views.editor.*
import miniceduapp.views.styles.Styles
import org.fxmisc.richtext.CodeArea
import tornadofx.*

class BytecodeView : View("Generated bytecode") {
    val viewModel: BytecodeViewModel by inject()

    var codeArea: CodeArea by singleAssign()

    override val root = hbox(10) {
        addClass(Styles.windowContent)
        codeArea = codeEditor(paneOp = {
            hgrow = Priority.ALWAYS
        }) {
            addSyntaxHighlighting(MiniCSyntaxHighlighter())
            isEditable = false
            //showLineNumbers() // weird bug, onDock doesn't fire if called here
        }
        stackpane {
            hgrow = Priority.ALWAYS
            maxWidth = 500.0
            tableview(viewModel.bytecode) {
                selectionModel = null
                hideHeader()
                column("", BytecodeLine::line).cellFormat {
                    text = it.toString()
                    alignment = Pos.TOP_CENTER
                    style {
                        textFill = c("#666666")
                        backgroundColor += c("#dddddd")
                    }
                }
                column("", BytecodeLine::instructions).cellFormat {
                    text = it.map { it.indent() + it.text }.joinToString("\n")
                    style {
                        backgroundColor += Color.WHITE
                    }
                }
                columnResizePolicy = SmartResize.POLICY
                placeholder = label("")
            }

            imageview("loading.gif") {
                visibleWhen { viewModel.status.running }
            }
        }
    }

    init {
        viewModel.programCodeProperty.onChange {
            codeArea.replaceText(it)
        }
    }

    override fun onDock() {
        setWindowMinSize(900, 600)

        codeArea.showLineNumbers()

        viewModel.loadBytecode()
    }

    fun Instruction.indent() = when (this) {
        is Label -> ""
        else -> "  "
    }
}
